package com.superman.auth.interceptor;

import com.superman.auth.service.AuthService;
import com.superman.auth.service.AuthSetting;
import com.superman.auth.service.impl.DefaultAuthSetting;
import org.springframework.lang.NonNull;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 权限拦截器
 * 拦截器（Interceptor）：是一种动态拦截方法调用的机制，在SpringMVC中动态拦截控制器方法的执行（类似有保安拦截检查，正常才通过）
 * 作用：在指定的方法调用前后执行预先设定的代码（比如权限的校验就是在访问controller之前校验）阻止原始方法的执行（把原始的方法终止掉）
 * Author: superman
 * Date: 2024/5/28 18:03
 */
public class AuthInterceptor implements HandlerInterceptor {

    private AuthSetting authSetting;
    private AuthService authService;

    public AuthInterceptor(AuthService authService) {
        this.authSetting = new DefaultAuthSetting() {
        };
        this.authService = authService;
    }

    public AuthInterceptor(AuthSetting authSetting, AuthService authService) {
        this.authSetting = authSetting;
        this.authService = authService;
    }

    /**
     * 调用时间：Controller 方法处理之前
     * 执行顺序：链式 Interceptor 情况下，Interceptor 按照声明的顺序一个接一个执行
     * 注意事项：若返回false，则中断执行，不会进入afterCompletion
     */
    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            if (authSetting.loginCheck()) {
                // 登录校验
                authService.loginCheck(request, response, handlerMethod);
            }
            if (authSetting.dataPermissionCheck()) {
                // 数据权限校验 + API是否禁用
                authService.dataPermissionCheck(request, response, handlerMethod);
            }
            if (authSetting.signCheck()) {
                // 签名检验
                authService.signCheck(request, response, handlerMethod);
            }
        }
        return true;
    }

    /**
     * 调用前提：preHandle返回true
     * 调用时间：Controller方法处理完之后，DispatcherServlet进行视图的渲染之前，也就是说在这个方法中你可以对ModelAndView进行操作
     * 执行顺序：链式 Interceptor 情况下，Interceptor 按照声明的顺序 `倒着` 执行
     */
    @Override
    public void postHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler,
                           ModelAndView modelAndView) throws Exception {
    }

    /**
     * 调用前提：preHandle返回true
     * 调用时间：DispatcherServlet进行视图渲染之后
     * 注意事项：多用于清理资源
     */
    @Override
    public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, Exception ex) throws Exception {
    }

}
